package audio;

import java.util.ArrayList;

import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;

abstract public class AudioBase implements LineListener
{
	private static final long serialVersionUID = 1;
	
	private ArrayList<AudioListener> listeners;
	
	/*
	 * Funções acessadas fora da máquina de estados
	 */
	abstract public void abortar();
	abstract public void encerrar() throws AudioException;
	
	/*
	 * Funções da máquina de estado
	 */
	abstract protected void estadoIniciar()  throws AudioException;
	abstract protected void estadoTocar()    throws AudioException;
	abstract protected void estadoTestar()   throws AudioException;
	
	protected String whoIAm;

	static final int PARADO       = 0;
	static final int INICIAR      = 1;
	static final int TOCAR        = 2;
	static final int TESTAR       = 3;
	static final int ENCERRAR	  = 4;
	static final int NORMALIZAR	  = 5;
	static final int DESCONECTADO = 6;
	static protected int estado = PARADO;

	public static int getEstado()			{ return estado;	}
	public static void setEstado(int e)		{ estado = e;		}
	public String getWhoIAm()				{ return whoIAm;	}

	protected AudioBase()
	{
		listeners = new ArrayList<AudioListener>();
	}

	/*
	 * Manipulação do Evento SoundEvent
	 */
	
	//	Registra novo ouvinte para o evento SoundEvent	
	public void addAudioListener(AudioListener listener) 
	{
		listeners.add(listener);
	}
    
	//	Cancela registro de ouvinte para o evento SoundEvent	
	public void removeAudioListener(AudioListener listener) 
	{
		while (listeners.remove(listener))
			;
	}
	
	//	Obtem todos os ouvintes para o evento SoundEvent	
	public AudioListener[] getAudioListeners()
	{
		return listeners.toArray(new AudioListener[listeners.size()]);
	}

	/*
	 *	Insere um evento SoundEvent na fila de eventos do sistema
	 *	Existe uma thread só para atender essa fila
	 *	Ela executa o método processEvent da "fonte" do evento
	 *	Fonte do evento = objeto que executou o método fireSoundEvent
	 */
	public void mandaEventoSilencio() 
	{
		System.out.println( whoIAm + " - MANDAR SILENCIO " );
		for (AudioListener listener : listeners) 
			listener.FimDeFala(new AudioEvent(this));
	}
    
	public void mandaEventoErro( String msg ) 
	{
		for (AudioListener listener : listeners) 
			listener.ErroAudio(new AudioEvent(this, msg));
	}

	@Override
	public void update(LineEvent e) 
	{
		if ( e.getType() == LineEvent.Type.STOP )
		{
			if ( estado == TESTAR )
				mandaEventoSilencio();
			estado = PARADO;
		}
	}
}
